package com.zs.basic.runoob

/**
 *
 * @description
 * @author madison
 * @date 2021/6/4 08:52
 *
 */
class User(var name: String)

/**扩展函数**/
fun User.Print() {
    println("用户名 $name")
}

// 扩展函数 swap,调换不同位置的值
fun MutableList<Int>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] //  this 对应该列表
    this[index1] = this[index2]
    this[index2] = tmp
}

//扩展函数是静态解析的
open class C2

class D1 : C2()

fun C2.foo() = "c"   // 扩展函数 foo

fun D1.foo() = "d"   // 扩展函数 foo

fun printFoo(c: C2) {
    println(c.foo())  // 类型是 C 类
}

//若扩展函数和成员函数一致，则使用该函数时，会优先使用成员函数。
class C3 {
    fun foo() {
        println("成员函数")
    }
}

fun C3.foo() {
    println("扩展函数")
}

//扩展一个空对象
fun Any?.toString(): String {
    if (this == null) return "null111"
    // 空检测之后，“this”会自动转换为非空类型，所以下面的 toString()
    // 解析为 Any 类的成员函数
    return toString()
}

//扩展属性
//除了函数，Kotlin 也支持属性对属性进行扩展:
val <T> List<T>.lastIndex: Int
    get() = size - 1

//伴生对象的扩展
class MyClass {
    companion object   // 将被称为 "Companion"
}

fun MyClass.Companion.foo() {
    println("伴随对象的扩展函数")
}

val MyClass.Companion.no: Int
    get() = 10

//扩展的作用域
//通常扩展函数或属性定义在顶级包下:
//
//package foo.bar
//
//fun Baz.goo() { …… }
//要使用所定义包之外的一个扩展, 通过import导入扩展的函数名进行使用:
//
//package com.example.usage
//
//import foo.bar.goo // 导入所有名为 goo 的扩展
//// 或者
//import foo.bar.*   // 从 foo.bar 导入一切
//
//fun usage(baz: Baz) {
//    baz.goo()
//}

//扩展声明为成员
class D2 {
    fun bar() {
        println("D bar")
    }
}

class C4 {
    fun baz() {
        println("C baz")
    }

    fun D2.foo() {
        bar()   // 调用 D.bar
        baz()   // 调用 C.baz
    }

    fun caller(d: D2) {
        d.foo()   // 调用扩展函数
    }
}

//在 C 类内，创建了 D 类的扩展。此时，C 被成为分发接受者，而 D 为扩展接受者。从上例中，可以清楚的看到，
// 在扩展函数中，可以调用派发接收者的成员函数。
//假如在调用某一个函数，而该函数在分发接受者和扩展接受者均存在，则以扩展接收者优先，
// 要引用分发接收者的成员你可以使用限定的 this 语法。
class D3 {
    fun bar() {
        println("D bar")
    }
}

class C5 {
    fun bar() {
        println("C bar")
    }

    fun D3.foo() {
        bar()
        this@C5.bar()
    }

    fun caller(d: D3) {
        d.foo()
    }
}

//以成员的形式定义的扩展函数, 可以声明为 open , 而且可以在子类中覆盖.
// 也就是说, 在这类扩展函数的派 发过程中, 针对分发接受者是虚拟的(virtual), 但针对扩展接受者仍然是静态的。
open class D4 {
}

class D5 : D4() {
}

open class C6 {
    open fun D4.foo() {
        println("D4.foo in C6")
    }

    open fun D5.foo() {
        println("D5.foo in C6")
    }

    fun caller(d: D4) {
        d.foo()   // 调用扩展函数
    }
}

class C7 : C6() {
    override fun D4.foo() {
        println("D4.foo in C7")
    }

    override fun D5.foo() {
        println("D5.foo in C7")
    }
}

fun main() {
    var user = User("Runbbo")
    user.Print()

    val l = mutableListOf<Int>(1, 2, 3)
    // 位置 0 和 2 的值做了互换
    l.swap(0, 2) // 'swap()' 函数内的 'this' 将指向 'l' 的值
    println(l.toString())

    printFoo(D1())
    var c = C3()
    c.foo()

    var t: Nothing? = null
    println(t.toString())

    println("no:${MyClass.no}")
    MyClass.foo()

    val c4 = C4()
    val d2 = D2()
    c4.caller(d2)

    val c5 = C5()
    val d3 = D3()
    c5.caller(d3)

    C6().caller(D4())
    C7().caller(D4())
    C6().caller(D5())
}